#ifndef CHESS_H
#define CHESS_H

#include <QString>
#include <optional>
#include <QTextStream>
#include <QList>

#include "config.h"
#include "base.h"

namespace Code {        // 前置声明
    struct Selector;
    class Pieces;
}

namespace Chess {       // 该名字空间负责读取残局记录信息

    using std::optional;

    struct Format_error {       // 文本格式错误异常
        Format_error(QString&& message, QString&& code) : message{std::move(message)}, code{std::move(code)} { }
        Format_error(QString&& message) : message{std::move(message)} { }
        Format_error(const char* message, QString&& code) : Format_error{QString{message},std::move(code)} { }
        QString message;
        QString code;
    };

    class Pieces : public Base::Base_pieces {      // Pieces是一个带有子力名（比如仕相全）的子力形势
    public:
        explicit Pieces(const QString& total_name) : total{total_name} { analyse(); }
        using Base_pieces::contains;
        Class_enum type() const;        // 类别
        const QString& name() const { return total; }
        void camp(bool red);        // 将子力设置正确阵营
        bool match(const Code::Pieces& other) const;        // 判断查询的子力状态是否匹配
    private:
        QString total;
        void analyse();     // 从total名中分析子力配置
        bool operator==(const Code::Pieces& other) const;       // 判断子力是否精确相同
        bool contains(const Code::Pieces& chess) const;     // 包含指定子力
    };

    class Message {     // Message类是一条残局信息
    public:
        explicit Message(QString&& line) { read(std::move(line)); }
        QString html() const;       // 转为html代码
        QString text() const { return QString{"%1-%2 / %3 / %4 / %5\n"}.arg(attack->name()).arg(defence->name()).arg(win).arg(difficulty).arg(strategy); }
        Class_enum type() const { return attack->type(); }
        bool selected(const Code::Selector& selector) const;        // 这条残局信息是否符合用户的选择器
    private:
        optional<Pieces> attack;
        optional<Pieces> defence;
        QString win;
        int difficulty;
        QString strategy;
        void read(QString&& line);      // 读取一条文字信息
    };

    class Class {       // Class类是一类残局信息
    public:
        explicit Class(Class_enum type) : type{type} { }
        QString html() const;       // 转为html代码
        QString text() const;       // 转为纯文本
        void append(Message&& m) { messages.append(std::move(m)); }
        void append(QList<Message>&& ms) { messages.append(std::move(ms)); }
        bool match(const Message& m) const { return m.type()==type; }
        QList<Message> select(const Code::Selector& selector) const;        // 选出符合条件的残局信息
        Class_enum get_type() const { return type; }
    private:
        Class_enum type;
        QList<Message> messages;
        const QString& name_class() const { return class_name[static_cast<int>(type)]; }
    };

}

#endif // CHESS_H
